package main

import (
	"net/http"
	"github.com/mediocregopher/radix.v2/cluster"
	"fmt"
	"encoding/json"
	"sort"
	"strings"
	"strconv"
	"runtime"
)

const (
	SimpleStr = 1 << iota
	BulkStr
	IOErr  // An error which prevented reading/writing, e.g. connection close
	AppErr // An error returned by redis, e.g. WRONGTYPE
	Int
	Array
	Nil
	Str = SimpleStr | BulkStr
	Err = IOErr | AppErr
)

type RSSIRecord struct {
	Major int
	Minor int
	Rssi int
	ProximityUUID string
}

type byRssi []RSSIRecord

func (v byRssi) Len() int {return len(v)}
func (v byRssi) Swap(i, j int) {v[i], v[j] = v[j], v[i]}
func (v byRssi) Less(i, j int) bool {return v[i].Rssi < v[j].Rssi}

var C, _ = cluster.New("192.168.1.201:7401")

var _ = runtime.GOMAXPROCS(8)

func response(str string, rw http.ResponseWriter, request *http.Request) {
	rw.Write([]byte(str))
}

func responseBytes(bytes []byte, rw http.ResponseWriter, request *http.Request) {
	rw.Write(bytes)
}

func listAd(c *cluster.Cluster, endUserSn string, triggerType string, appToken string, jsonBeacons string) ([]byte) {
	var f byRssi

	jsonErr := json.Unmarshal([]byte(jsonBeacons), &f)

	if jsonErr != nil {
		fmt.Println("JSON Parse Error: ", jsonErr)
	}

	sort.Sort(f)

	var posIds []string

	for _, v := range f {
		ret := C.Cmd("GET", "UMM:POSID:" + strings.ToUpper(v.ProximityUUID) + ":" + strconv.Itoa(v.Major) + ":" + strconv.Itoa(v.Minor))

		if ret.IsType(Str) {
			s, _ := ret.Str()
			posIds = append(posIds, s)
		}
	}

	var planIds []string

	for _, v := range posIds {
		ret := C.Cmd("ZRANGE", "POSID:PLANID:" + v, 0, -1)

		if ret.IsType(Array) {
			s, _ := ret.Array()

			for _, vv := range s {
				sp, _ := vv.Str()
				planIds = append(planIds, sp)
			}
		}
	}

	var ads []byte

	ads = append(ads, '[')

	for _, v := range planIds {
		ret := C.Cmd("GET", "ADPLAN:ADC:" + v)

		if ret.IsType(Str) {
			s, _ := ret.Bytes()
			ads = append(ads, s...)
		}
	}

	ads = append(ads, ']')

	return ads
}

func listAdRequest(rw http.ResponseWriter, request *http.Request) {
	res := listAd(
		C,
		request.FormValue("endUserSn"),
		request.FormValue("triggerType"),
		request.FormValue("appToken"),
		request.FormValue("jsonBeacons"),
	)
	responseBytes(res, rw, request)
}

func simpleRequest(rw http.ResponseWriter, request *http.Request) {
	response("Hello World", rw, request)
}

func main() {
	http.HandleFunc("/ids/testConn.action", simpleRequest)
	http.HandleFunc("/ids/listAdsOfBeaconsMem.action", listAdRequest)
	http.ListenAndServe(":3000", nil)
}